#pragma once

#include <iostream>
#include <xtd/bistream>
#include <xtd/bostream>

namespace g3 {

template <class T> class basic_vector;
template <class T> class basic_matrix;
template <class T> class basic_smatrix;

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_vector<T> & v)
	{ return s << v.x << ' ' << v.y << ' ' << v.z; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_vector<T> & v)
	{ return s >> v.x >> v.y >> v.z; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_smatrix<T> & m)
	{ return s << m.xx << ' ' << m.xy << ' ' << m.xz << ' ' << m.yy << ' ' << m.yz << ' ' << m.zz; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_smatrix<T> & m)
	{ return s >> m.xx >> m.xy >> m.xz >> m.yy >> m.yz >> m.zz; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_matrix<T> & m) {
	int i, j;
	for (i = 0; i < 3; ++i)
		for (j = 0; j < 3; ++j) {
			if (i != 0 || j != 0)
				s << ' ';
			s << m(i,j);
		}
	return s;
}

template <class T>
inline std::istream & operator >> (std::istream & s, basic_matrix<T> & m) {
	int i, j;
	for (i = 0; i < 3; ++i)
		for (j = 0; j < 3; ++j) {
			s >> m(i,j);
		}
	return s;
}

//binary

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_vector<T> & v)
	{ return s.put(v); }

template <typename T>
inline xtd::bistream & operator >> (xtd::bistream & in, basic_vector<T> & v) {
	return in.get(v);
}

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_smatrix<T> & m)
	{ return s.put(m); }

template <typename T>
inline xtd::bistream & operator >> (xtd::bistream & in, basic_smatrix<T> & m) {
	return in.get(m);
}

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_matrix<T> & m)
	{ return s.put(m); }

template <typename T>
inline xtd::bistream & operator >> (xtd::bistream & in, basic_matrix<T> & m) {
	return in.get(m);
}

} // g3
